import pickledb
from xjlibrary.our_file_dir import BaseDir

curpath = BaseDir.get_file_dir_absolute(__file__)
toppath = BaseDir.get_upper_dir(curpath, -2)
pickledbdir = BaseDir.get_new_path(toppath, "dbdata", "pickledbdata")
BaseDir.create_dir(pickledbdir)


class MPickleDB(object):
    dbpath = BaseDir.get_new_path(pickledbdir, "all.db")
    # 从文件反序列化，auto_dump 是每次写入操作都会写到文件，可以设置为False避免多次io
    db = pickledb.load(dbpath, False)

    @classmethod
    def set_db(cls, dbpath, auto_dump):
        cls.dbpath = dbpath
        cls.db = pickledb.load(dbpath, auto_dump)

    @classmethod
    def delete_file(cls):
        BaseDir.remove_file(cls.dbpath)

    @classmethod
    def set(cls, key, value):
        """
        设置键的字符串值,键值重复不会报错,也不会返回False,
        值改变会被当作更新操作
        :param key:
        :param value:
        :return:
        """
        return cls.db.set(key, value)

    @classmethod
    def get(cls, key):
        """
        获取密钥的值，没有键会返回False
        :param key:
        :return:
        """
        return cls.db.get(key)

    @classmethod
    def dump(cls):
        """
        强制转换内存数据到文件,如果不调用数据在内存中
        :return:
        """
        return cls.db.dump()

    @classmethod
    def get_all(cls):
        """
        返回一个列表，列表为所有的键
        :return:
        """
        return cls.db.getall()

    @classmethod
    def delete(cls, key):
        """
        删除键值对，删除没有的key会出现 KeyError 错误
        :param key:
        :return:
        """
        return cls.db.rem(key)

    @classmethod
    def append(cls, key, more):
        """
        会被追加到字符串里 而不是生成列表
        不能追加key不存在的值 会报KeyError 错
        :param key:
        :param more:
        :return:
        """
        return cls.db.append(key, more)

    @classmethod
    def lcreate(cls, name):
        """
        创建一个列表值
        如果name 存在并有值，再次调用创建会清除原来的值,
        并且不会给出任何提示
        :return:
        """
        return cls.db.lcreate(name)

    @classmethod
    def ladd(cls, name, value):
        """
        将值添加到列表中,不能使用没有创建的列表名，报 KeyError
        相同的值不会覆盖会在列表中如  ["234", "234"]
        :param name:
        :param value:
        :return:
        """
        return cls.db.ladd(name, value)

    @classmethod
    def lgetall(cls, name):
        """
        返回列表中的所有值，name不存在时 报 KeyError
        存在时返回列表
        :param name:
        :return:
        """
        return cls.db.lgetall(name)

    @classmethod
    def lextend(cls, name, seq):
        """
        使用序列扩展列表 name必须存在 否则 KeyError
        :param name:
        :param seq: 传入字符串将被分割成列表 传入list会被追加到list后面
        传入元组和list效果一样,如果传入字典只能识别到key并被加入
        :return:
        """
        return cls.db.lextend(name, seq)

    @classmethod
    def lget(cls, name, pos):
        """
        返回列表中的一个值  name必须存在 否则 KeyError
        pos 为int 从0开始 超出提示 IndexError: list index out of range
        :return:
        """
        return cls.db.lget(name, pos)

    @classmethod
    def lremlist(cls, name):
        """
        删除列表及其所有值  name必须存在 否则 KeyError
        整个name都会被删除而不是列表为[]
        :param name:
        :return: 删除数据的长度 及list的长度
        """
        return cls.db.lremlist(name)

    @classmethod
    def lpop(cls, name, pos):
        """
        删除列表中的一个值 name必须存在 否则 KeyError
        :param name:
        :param pos: 不能超过上线 IndexError: list index out of range
        :return: 返回删除的值
        """
        return cls.db.lpop(name, pos)

    @classmethod
    def llen(cls, name):
        """
        返回列表的长度 name必须存在 否则 KeyError
        :param name:
        :return: 返回list的长度
        """
        return cls.db.llen(name)

    @classmethod
    def lappend(cls, name, pos, more):
        """
        在列表中指定位置添加更多值，不是在指定位置插入值
        例如 0位置原来是"d" ,插入1 就变成了 "d1" 而list的长度不变
        :param name:
        :param pos:
        :param more:
        :return:
        """
        return cls.db.lappend(name, pos, more)

    @classmethod
    def dcreate(cls, name):
        """
        创建一个字典
        如果name 存在并有值，再次调用创建会清除原来的值,
        并且不会给出任何提示
        :param name:
        :return:
        """
        return cls.db.dcreate(name)

    @classmethod
    def dadd(cls, name, pair):
        """
        name必须存在 否则 KeyError:
        将一个键值对添加到dict中，“pair”是一个元组
        key 存在会做更新操作
        :param name:
        :param pair:
        :return:
        """
        return cls.db.dadd(name, pair)

    @classmethod
    def dgetall(cls, name):
        """
        返回dict中的所有键值对
        :param name:
        :return:
        """
        return cls.db.dgetall(name)

    @classmethod
    def dget(cls, name, key):
        """
        返回dict中键的值
        :param name:
        :param key:
        :return:
        """
        return cls.db.dget(name, key)

    @classmethod
    def dkeys(cls, name):
        """
        返回dict的所有键
        :param name:
        :return: 类型为dict_keys(['key', 'key1'])
        """
        return cls.db.dkeys(name)

    @classmethod
    def dvals(cls, name):
        """
        返回自0.6以来的dict （可用）的所有值
        :param name:
        :return: dict_values(['value', 'value123'])
        """
        return cls.db.dvals(name)

    @classmethod
    def dexists(cls, name, key):
        """
        确定是否存在密钥
        :param name:
        :param key:
        :return:
        """
        return cls.db.dexists(name, key)

    @classmethod
    def dpop(cls, name, key):
        """
        删除dict中的一个键值
        :param name:
        :param key: 返回值 value123
        :return:
        """
        return cls.db.dpop(name, key)

    @classmethod
    def drem(cls, name):
        """
        删除dict及其所有对,不能删除不存在的字典
        完全删除而不是清空字典的值
        :param name:
        :return:
        """
        return cls.db.drem(name)

    @classmethod
    def deldb(cls):
        """
        从数据库中删除所有内容
        清空  但文件不会被删除
        :return:
        """
        return cls.db.deldb()
